package main

import (
	"fmt"
	"log"
	"math"
)

func init() {
	fmt.Println("calculate init")
	log.Println("calculate init")
}

//斜率
func Slope(a1, b1 loct) float64 {
	var (
		y1 = float64(a1.y)
		x1 = float64(a1.x)
		y2 = float64(b1.y)
		x2 = float64(b1.x)
	)
	if x1 == x2 {
		return 0
	}
	return (y2 - y1) / (x2 - x1)
}

//坐标距离
func CoorDistance(a, b loct) float64 {
	return math.Pow(float64(a.x-b.x), 2) + math.Pow(float64(a.y-b.y), 2)
}

//角度
func AngleEquation(a, b loct, mpi int) float64 {
	x := math.Abs(float64(a.x - b.x))
	y := math.Abs(float64(a.y - b.y))
	z := math.Sqrt(x*x + y*y)
	as := math.Asin(y/z) / math.Pi * 180 //角度换算 180 360
	return as
}

//一元一次方程 y=ax+b
func ObliqueEquation(a1, b1 loct) loct {
	var (
		y1 = float64(a1.y)
		y2 = float64(b1.y)
		x1 = float64(a1.x)
		x2 = float64(b1.x)
	)
	nx := x1
	if x2 > x1 {
		nx += DENSITY
	} else if x2 < x1 {
		nx -= DENSITY
	}
	y := y1 - y2
	x := x1 - x2
	a := y / x
	b := y1 - x1*y/x
	ny := a*nx + b
	return loct{x: int(round(nx, 0)), y: int(round(ny, 0))}
}

// 直线的一般式方程 Ax+By+C=0（A，B不全为零即A^2+B^2≠0）
func GeneralEquation(a1, b1 loct) loct {
	log.Println(Slope(a1, b1))
	r := loct{}
	var (
		y1 = float64(a1.y)
		y2 = float64(b1.y)
		x1 = float64(a1.x)
		x2 = float64(b1.x)
	)
	a := y2 - y1
	b := x1 - x2
	c := x2*y1 - x1*y2
	var (
		x = nrxy(x2, x1)
		y = y1 //nrxy(y2, y1)
	)
	if a*a != 0 || b*b != 0 {
		if x == x2 {
			r.x = int(x)
			r.y = int(y)
		} else if y == y2 {
			r.x = int(x)
			r.y = int(y)
		} else if x != x2 && y != y2 {
			ax := a * x
			tc := c + ax
			gys := float64(gcd(int(tc), int(b)))
			y = math.Abs((tc / gys) / (b / gys))
			if tc+b*y == 0 {
				r.x = int(round(x, 0))
				r.y = int(round(y, 0))
			}
			//log.Println("开始 =", a1, " 目标 =", b1, " 移动后 =", r)
		}
	}
	return r
}

//
func nrxy(a, b float64) float64 {
	if a > b {
		return b + DENSITY
	} else if a < b {
		return b - DENSITY
	}
	return b
}

//四舍五入
func round(val float64, places int) float64 {
	var t float64
	f := math.Pow10(places)
	x := val * f
	if math.IsInf(x, 0) || math.IsNaN(x) {
		return val
	}
	if x >= 0.0 {
		t = math.Ceil(x)
		if (t - x) > 0.50000000001 {
			t -= 1.0
		}
	} else {
		t = math.Ceil(-x)
		if (t + x) > 0.50000000001 {
			t -= 1.0
		}
		t = -t
	}
	x = t / f
	if !math.IsInf(x, 0) {
		return x
	}
	return t
}

/*
*辗转相除法：最大公约数
*递归写法，进入运算是x和y都不为0
 */
func gcd(x, y int) int {
	tmp := x % y
	if tmp > 0 {
		return gcd(y, tmp)
	} else {
		return y
	}
}

/*
*辗转相除法：最大公约数
*非递归写法
 */
func gcdx(x, y int) int {
	var tmp int
	for {
		tmp = (x % y)
		if tmp > 0 {
			x = y
			y = tmp
		} else {
			return y
		}
	}
}

/*
*公式解法：最小公倍数=两数之积/最大公约数
 */
func lcm(x, y int) int {
	return x * y / gcd(x, y)
}
